<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>debounce sample</title>
</head>

<body>
    <h3>
        <ul>
            <li>打开console</li>
            <li>快速滚动鼠标滚动轮</li>
        </ul>
    </h3>
    <div style="height: 1500px;"></div>

    <script>
        /**
         * 简单的`debounce`函数实现
         *
         * @param {function} cb 要执行的回调函数
         * @param {number} delay 要等待的防抖延迟时间
         * @returns {function}
         */
        const debounce = function (cb, delay) {
            // 参数检查
            //   cb：function
            //   delay：number
            if (toString.call(cb) !== '[object Function]') {
                throw new Error(`${cb} is not a function.`)
            }
            // 没有传 delay 参数时（包括等于0）
            if (!delay) {
                delay = 500 // 设置默认延时
            }
            // delay 参数须为正整数
            else if (!Number.isInteger(delay) || delay < 0) {
                throw new Error(`${delay} is invalid as optional parameter [delay]`)
            }

            // 定时器
            let timer = null

            // 返回debounce包装过的执行函数
            return function (...args) {
                // 如果存在定时器
                if (timer) {
                    // 清除定时器，
                    // 即：忽略之前的触发
                    clearTimeout(timer)
                }

                // 设置定时器
                timer = setTimeout(() => {
                    // 当到了设定的时间：
                    //   清除本次定时器，
                    //   并执行函数
                    clearTimeout(timer)
                    timer = null
                    cb.call(null, ...args)
                }, delay);
            }
        }

        // scroll in debounce
        const realEventHandler = function() {
            console.log('scroll in debounce')
        }
        const debouncedScrollHandler = debounce(realEventHandler, 500)
        window.addEventListener('scroll', debouncedScrollHandler)
    </script>
</body>

</html>